import { Application } from "../Application";
import { logger } from "../util/logger";
import { miscCfg, RpcMsg, RpcMsgId, SvrInfo } from "../util/defines";
import { RpcSocket } from "./RpcSocket";
import { TcpClient } from "../tcp/TcpClient";

/**
 * Rpc客户端
 */
export class RpcClient extends RpcSocket {

    private _hbTimer: NodeJS.Timeout;
    private _hbTimeoutTimer: NodeJS.Timeout;

    constructor(app: Application, remoteSvr: SvrInfo) {
        super(app, remoteSvr);
        this.connect();
    }

    private connect() {
        logger.info(`${this.app.svr.id}尝试与${this.remoteSvr.id}建立Rpc连接`, this, this.connect);
        this.socket = new TcpClient(this.remoteSvr.port, this.remoteSvr.host, this.onConnect.bind(this));
        this.socket.on(this.onUnregData.bind(this), this.onUnregClose.bind(this));
    }

    private onConnect() {
        logger.info(`${this.app.svr.id}连接${this.remoteSvr.id}成功,开始注册`, this, this.onConnect);
        this.socket.sendReg({ token: miscCfg.svrToken, sid: this.app.svr.id });
    }

    /**
     * 注册前的消息
     * @param data 
     */
    private onUnregData(data: { msgId: RpcMsgId, msg: RpcMsg }) {
        if (data.msgId === RpcMsgId.regOk) {
            if (this.onReg(this.socket)) {
                this.sendHeartbeat();
                this.app.rpcService.runWaitConnCbs(this.remoteSvr.id, null, this);
            }
        }
    }

    /**
     * 注册前的关闭
     */
    private onUnregClose() {
        let err = `连接${this.remoteSvr.id}失败`;
        logger.error(err, this, this.onUnregClose);
        this.app.rpcService.runWaitConnCbs(this.remoteSvr.id, err);
    }

    protected onMsg(data: { msgId: RpcMsgId, msg: RpcMsg }) {
        switch (data.msgId) {
            case RpcMsgId.heartbeat:
                clearTimeout(this._hbTimeoutTimer);
                this._hbTimer = setTimeout(this.sendHeartbeat.bind(this), miscCfg.heartbeatTime);
                return;
        }
    }

    protected onClose() {
        clearTimeout(this._hbTimer);
        clearTimeout(this._hbTimeoutTimer);
        logger.error(`${this.app.svr.id}与${this.remoteSvr.id}断开连接`, this, this.onClose);
    }

    private sendHeartbeat() {
        this.send(RpcMsgId.heartbeat);
        this._hbTimeoutTimer = setTimeout(this.onHeartbeatTimeout.bind(this), miscCfg.heartbeatTimeout);
    }

    private onHeartbeatTimeout() {
        logger.error(`${this.remoteSvr.id}心跳包返回超时`, RpcClient, this.onHeartbeatTimeout);
        this.close();
    }

}